home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / winsr173.zip / WGENERAL.ASM < prev    next >
Assembly Source File  |  1992-06-03  |  13KB  |  509 lines

  1. ;    Generic assembler routines that have very little at all
  2. ;    to do with fractals.
  3. ;
  4. ;
  5. ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
  6. ;
  7. ;    multiply()
  8. ;    divide()
  9. ;
  10.  
  11. .MODEL    medium,c
  12.  
  13. ; I don't know why this has to be here, but BC++ won't create public
  14. ; symbols without it.
  15.  
  16. public multiply, divide, toextra, fromextra, cmpextra
  17.  
  18.  
  19. .8086
  20.  
  21. .DATA
  22.  
  23.  
  24. ; ************************ Public variables *****************************
  25.  
  26. public        overflow        ; Mul, Div overflow flag: 0 means none
  27.  
  28. ;        arrays declared here, used elsewhere
  29. ;        arrays not used simultaneously are deliberately overlapped
  30.  
  31. public        prefix, suffix, dstack, decoderline ; for the Decoder
  32. public        strlocn, teststring, block    ; used by the Encoder
  33. public        boxx, boxy, boxvalues        ; zoom-box arrays
  34. public        olddacbox            ; temporary DAC saves
  35. public        rlebuf                ; Used ty the TARGA En/Decoder
  36.  
  37. ; ************************* "Shared" array areas **************************
  38.  
  39. ; Short forms used in subsequent comments:
  40. ;   name........duration of use......................modules....................
  41. ;   encoder    "s"aving an image                    encoder.c
  42. ;   decoder    "r"estoring an image                 decoder.c, gifview.c
  43. ;   zoom    zoom box is visible             zoom.c, video.asm
  44. ;   vidswitch    temp during video mode setting         video.asm
  45. ;   vidreset    temp during video reset          prompts.c, fractint.c, rotate.c, cmdfiles.c
  46. ;   tgaview    restore of tga image             tgaview.c
  47. ;   solidguess    image gen with "g", not to disk      calcfrac.c
  48. ;   btm     image gen with "b", not to disk      calcfrac.c
  49.  
  50. block        label    byte        ; encoder(266)
  51. suffix        dw    2048 dup(0)    ; decoder(4k), vidswitch(256)
  52.  
  53. teststring    label    byte        ; encoder(100)
  54. dstack        dw    2048 dup(0)    ; decoder(4k), solidguess(4k), btm(2k)
  55.                     ;   zoom(2k)
  56.  
  57. strlocn     label    word        ; encoder(10k)
  58. prefix        label    word        ; decoder(8k), solidguess(6k)
  59. olddacbox    label    byte        ; vidreset(768)
  60. boxx        dw    2048 dup(0)    ; zoom(4k), tgaview(4k)
  61. boxy        dw    2048 dup(0)    ; zoom(4k)
  62. boxvalues    label    byte        ; zoom(2k)
  63. decoderline    db    2050 dup(0)    ; decoder(2049), btm(2k)
  64.  
  65. rlebuf        db    258 dup(0)    ; f16.c(258) .tga save/restore?
  66.  
  67. ; Internal Overflow flag
  68.  
  69. overflow    dw    0        ; overflow flag
  70.  
  71.  
  72. ; =======================================================
  73. ;
  74. ;    32-bit integer multiply routine with an 'n'-bit shift.
  75. ;    Overflow condition returns 0x7fffh with overflow = 1;
  76. ;
  77. ;    long x, y, z, multiply();
  78. ;    int n;
  79. ;
  80. ;    z = multiply(x,y,n)
  81. ;
  82. ;    requires the presence of an external variable, 'cpu'.
  83. ;        'cpu' == 386 if a 386 is present.
  84.  
  85. .8086
  86.  
  87. .DATA
  88.  
  89. extrn    cpu:word            ; cpu flag:     88 = 8088/8086
  90.                     ;        186 = 80188/186
  91.                     ;        286 = 80286
  92.                     ;        386 = 80386/486
  93. extrn    fpu:word            ; fpu flag:      0 = none
  94.                     ;         87 = 8087
  95.                     ;               287 = 80287
  96.                     ;        387 = 80387/(487)
  97.  
  98. temp    dw    5 dup(0)        ; temporary 64-bit result goes here
  99. sign    db    0            ; sign flag goes here
  100.  
  101. .CODE
  102.  
  103. multiply    proc    x:dword, y:dword, n:word
  104.  
  105.     cmp    cpu,386         ; go-fast time?
  106.     jne    slowmultiply        ; no.  yawn...
  107.  
  108. .386                    ; 386-specific code starts here
  109.  
  110.     mov    eax,x            ; load X into EAX
  111.     imul    y            ; do the multiply
  112.     mov    cx,n            ; set up the shift
  113.     cmp    cx,32            ; ugly klooge:    check for 32-bit shift
  114.     jb    short fastm1        ;  < 32 bits:  no problem
  115.     mov    eax,edx         ;  >= 32 bits:    manual shift
  116.     mov    edx,0            ;  ...
  117.     sub    cx,32            ;  ...
  118. fastm1: shrd    eax,edx,cl        ; shift down 'n' bits
  119.     js    fastm3
  120.     sar    edx,cl
  121.     jne    overmf
  122.     shld    edx,eax,16
  123.     ret
  124. fastm3: sar    edx,cl
  125.     inc    edx
  126.     jne    overmf
  127.     shld    edx,eax,16
  128.     ret
  129. overmf:
  130.     mov    ax,0ffffh        ; overflow value
  131.     mov    dx,07fffh        ; overflow value
  132.     mov    overflow,1        ; flag overflow
  133.     ret
  134.  
  135. .8086                    ; 386-specific code ends here
  136.  
  137. slowmultiply:                ; (sigh)  time to do it the hard way...
  138.     push    di
  139.     push    si
  140.  
  141.     mov    ax,0
  142.     mov    temp+4,ax        ; first, zero out the (temporary)
  143.     mov    temp+6,ax        ;  result
  144.     mov    temp+8,ax
  145.  
  146.     mov    bx,word ptr x        ; move X to SI:BX
  147.     mov    si,word ptr x+2        ;  ...
  148.     mov    cx,word ptr y        ; move Y to DI:CX
  149.     mov    di,word ptr y+2        ;  ...
  150.  
  151.     mov    sign,0            ; clear out the sign flag
  152.     cmp    si,0            ; is X negative?
  153.     jge    mults1            ;  nope
  154.     not    sign            ;  yup.  flip signs
  155.     not    bx            ;   ...
  156.     not    si            ;   ...
  157.     stc                ;   ...
  158.     adc    bx,ax            ;   ...
  159.     adc    si,ax            ;   ...
  160. mults1: cmp    di,0            ; is DI:CX negative?
  161.     jge    mults2            ;  nope
  162.     not    sign            ;  yup.  flip signs
  163.     not    cx            ;   ...
  164.     not    di            ;   ...
  165.     stc                ;   ...
  166.     adc    cx,ax            ;   ...
  167.     adc    di,ax            ;   ...
  168. mults2:
  169.  
  170.     mov    ax,bx            ; perform BX x CX
  171.     mul    cx            ;  ...
  172.     mov    temp,ax         ;  results in lowest 32 bits
  173.     mov    temp+2,dx        ;  ...
  174.  
  175.     mov    ax,bx            ; perform BX x DI
  176.     mul    di            ;  ...
  177.     add    temp+2,ax        ;  results in middle 32 bits
  178.     adc    temp+4,dx        ;  ...
  179.     jnc    mults3            ;  carry bit set?
  180.     inc    word ptr temp+6     ;  yup.  overflow
  181. mults3:
  182.  
  183.     mov    ax,si            ; perform SI * CX
  184.     mul    cx            ;  ...
  185.     add    temp+2,ax        ;  results in middle 32 bits
  186.     adc    temp+4,dx        ;  ...
  187.     jnc    mults4            ;  carry bit set?
  188.     inc    word ptr temp+6     ;  yup.  overflow
  189. mults4:
  190.  
  191.     mov    ax,si            ; perform SI * DI
  192.     mul    di            ;  ...
  193.     add    temp+4,ax        ; results in highest 32 bits
  194.     adc    temp+6,dx        ;  ...
  195.  
  196.     mov    cx,n            ; set up for the shift loop
  197.     cmp    cx,24            ; shifting by three bytes or more?
  198.     jl    multc1            ;  nope.  check for something else
  199.     sub    cx,24            ; quick-shift 24 bits
  200.     mov    ax,temp+3        ; load up the registers
  201.     mov    dx,temp+5        ;  ...
  202.     mov    si,temp+7        ;  ...
  203.     mov    bx,0            ;  ...
  204.     jmp    short multc4        ; branch to common code
  205. multc1: cmp    cx,16            ; shifting by two bytes or more?
  206.     jl    multc2            ;  nope.  check for something else
  207.     sub    cx,16            ; quick-shift 16 bits
  208.     mov    ax,temp+2        ; load up the registers
  209.     mov    dx,temp+4        ;  ...
  210.     mov    si,temp+6        ;  ...
  211.     mov    bx,0            ;  ...
  212.     jmp    short multc4        ; branch to common code
  213. multc2: cmp    cx,8            ; shifting by one byte or more?
  214.     jl    multc3            ;  nope.  check for something else
  215.     sub    cx,8            ; quick-shift 8 bits
  216.     mov    ax,temp+1        ; load up the registers
  217.     mov    dx,temp+3        ;  ...
  218.     mov    si,temp+5        ;  ...
  219.     mov    bx,temp+7        ;  ...
  220.     jmp    short multc4        ; branch to common code
  221. multc3: mov    ax,temp         ; load up the regs
  222.     mov    dx,temp+2        ;  ...
  223.     mov    si,temp+4        ;  ...
  224.     mov    bx,temp+6        ;  ...
  225. multc4: cmp    cx,0            ; done shifting?
  226.     je    multc5            ;  yup.  bail out
  227.  
  228. multloop:
  229.     shr    bx,1            ; shift down 1 bit, cascading
  230.     rcr    si,1            ;  ...
  231.     rcr    dx,1            ;  ...
  232.     rcr    ax,1            ;  ...
  233.     loop    multloop        ; try the next bit, if any
  234. multc5:
  235.     cmp    si,0            ; overflow time?
  236.     jne    overm1            ; yup.    Bail out.
  237.     cmp    bx,0            ; overflow time?
  238.     jne    overm1            ; yup.    Bail out.
  239.     cmp    dx,0            ; overflow time?
  240.     jl    overm1            ; yup.    Bail out.
  241.  
  242.     cmp    sign,0            ; should we negate the result?
  243.     je    mults5            ;  nope.
  244.     not    ax            ;  yup.  flip signs.
  245.     not    dx            ;   ...
  246.     mov    bx,0            ;   ...
  247.     stc                ;   ...
  248.     adc    ax,bx            ;   ...
  249.     adc    dx,bx            ;   ...
  250. mults5:
  251.     jmp    multiplyreturn
  252.  
  253. overm1:
  254.     mov    ax,0ffffh        ; overflow value
  255.     mov    dx,07fffh        ; overflow value
  256.     mov    overflow,1        ; flag overflow
  257.  
  258. multiplyreturn:             ; that's all, folks!
  259.     pop    si
  260.     pop    di
  261.     ret
  262. multiply    endp
  263.  
  264.  
  265. ; =======================================================
  266. ;
  267. ;    32-bit integer divide routine with an 'n'-bit shift.
  268. ;    Overflow condition returns 0x7fffh with overflow = 1;
  269. ;
  270. ;    long x, y, z, divide();
  271. ;    int n;
  272. ;
  273. ;    z = divide(x,y,n);    /* z = x / y; */
  274. ;
  275. ;    requires the presence of an external variable, 'cpu'.
  276. ;        'cpu' == 386 if a 386 is present.
  277.  
  278.  
  279. .8086
  280.  
  281. divide        proc    x:dword, y:dword, n:word
  282.  
  283.     push    di
  284.     push    si
  285.  
  286.     cmp    cpu,386         ; go-fast time?
  287.     jne    slowdivide        ; no.  yawn...
  288.  
  289. .386                    ; 386-specific code starts here
  290.  
  291.     mov    edx,x            ; load X into EDX (shifts to EDX:EAX)
  292.     mov    ebx,y            ; load Y into EBX
  293.  
  294.     mov    sign,0            ; clear out the sign flag
  295.     cmp    edx,0            ; is X negative?
  296.     jge    short divides1        ;  nope
  297.     not    sign            ;  yup.  flip signs
  298.     neg    edx            ;   ...
  299. divides1:
  300.     cmp    ebx,0            ; is Y negative?
  301.     jge    short divides2        ;  nope
  302.     not    sign            ;  yup.  flip signs
  303.     neg    ebx            ;   ...
  304. divides2:
  305.  
  306.     mov    eax,0            ; clear out the low-order bits
  307.     mov    cx,32            ; set up the shift
  308.     sub    cx,n            ; (for large shift counts - faster)
  309. fastd1: cmp    cx,0            ; done shifting?
  310.     je    fastd2            ; yup.
  311.     shr    edx,1            ; shift one bit
  312.     rcr    eax,1            ;  ...
  313.     loop    fastd1            ; and try again
  314. fastd2:
  315.     cmp    edx,ebx         ; umm, will the divide blow out?
  316.     jae    overd1            ;  yup.  better skip it.
  317.     div    ebx            ; do the divide
  318.     cmp    eax,0            ; did the sign flip?
  319.     jl    overd1            ;  then we overflowed
  320.     cmp    sign,0            ; is the sign reversed?
  321.     je    short divides3        ;  nope
  322.     neg    eax            ; flip the sign
  323. divides3:
  324.     push    eax            ; save the 64-bit result
  325.     pop    ax            ; low-order  16 bits
  326.     pop    dx            ; high-order 16 bits
  327.     jmp    dividereturn        ; back to common code
  328.  
  329. .8086                    ; 386-specific code ends here
  330.  
  331. slowdivide:                ; (sigh)  time to do it the hard way...
  332.  
  333.     mov    ax,word ptr x        ; move X to DX:AX
  334.     mov    dx,word ptr x+2        ;  ...
  335.  
  336.     mov    sign,0            ; clear out the sign flag
  337.     cmp    dx,0            ; is X negative?
  338.     jge    divides4        ;  nope
  339.     not    sign            ;  yup.  flip signs
  340.     not    ax            ;   ...
  341.     not    dx            ;   ...
  342.     stc                ;   ...
  343.     adc    ax,0            ;   ...
  344.     adc    dx,0            ;   ...
  345. divides4:
  346.  
  347.     mov    cx,32            ; get ready to shift the bits
  348.     sub    cx,n            ; (shift down rather than up)
  349.     mov    byte ptr temp+4,cl    ;  ...
  350.  
  351.     mov    cx,0            ;  clear out low bits of DX:AX:CX:BX
  352.     mov    bx,0            ;  ...
  353.  
  354.     cmp    byte ptr temp+4,16    ; >= 16 bits to shift?
  355.     jl    dividex0        ;  nope
  356.     mov    bx,cx            ;  yup.  Take a short-cut
  357.     mov    cx,ax            ;   ...
  358.     mov    ax,dx            ;   ...
  359.     mov    dx,0            ;   ...
  360.     sub    byte ptr temp+4,16    ;   ...
  361. dividex0:
  362.     cmp    byte ptr temp+4,8    ; >= 8 bits to shift?
  363.     jl    dividex1        ;  nope
  364.     mov    bl,bh            ;  yup.  Take a short-cut
  365.     mov    bh,cl            ;   ...
  366.     mov    cl,ch            ;   ...
  367.     mov    ch,al            ;   ...
  368.     mov    al,ah            ;   ...
  369.     mov    ah,dl            ;   ...
  370.     mov    dl,dh            ;   ...
  371.     mov    dh,0            ;   ...
  372.     sub    byte ptr temp+4,8    ;   ...
  373. dividex1:
  374.     cmp    byte ptr temp+4,0    ; are we done yet?
  375.     je    dividex2        ;  yup
  376.     shr    dx,1            ; shift all 64 bits
  377.     rcr    ax,1            ;  ...
  378.     rcr    cx,1            ;  ...
  379.     rcr    bx,1            ;  ...
  380.     dec    byte ptr temp+4     ; decrement the shift counter
  381.     jmp    short dividex1        ;  and try again
  382. dividex2:
  383.  
  384.     mov    di,word ptr y        ; move Y to SI:DI
  385.     mov    si,word ptr y+2        ;  ...
  386.  
  387.     cmp    si,0            ; is Y negative?
  388.     jge    divides5        ;  nope
  389.     not    sign            ;  yup.  flip signs
  390.     not    di            ;   ...
  391.     not    si            ;   ...
  392.     stc                ;   ...
  393.     adc    di,0            ;   ...
  394.     adc    si,0            ;   ...
  395. divides5:
  396.  
  397.     mov    byte ptr temp+4,33    ; main loop counter
  398.     mov    temp,0            ; results in temp
  399.     mov    word ptr temp+2,0    ;  ...
  400.  
  401. dividel1:
  402.     shl    temp,1            ; shift the result up 1
  403.     rcl    word ptr temp+2,1    ;  ...
  404.     cmp    dx,si            ; is DX:AX >= Y?
  405.     jb    dividel3        ;  nope
  406.     ja    dividel2        ;  yup
  407.     cmp    ax,di            ;  maybe
  408.     jb    dividel3        ;  nope
  409. dividel2:
  410.     cmp    byte ptr temp+4,32    ; overflow city?
  411.     jge    overd1            ;  yup.
  412.     sub    ax,di            ; subtract Y
  413.     sbb    dx,si            ;  ...
  414.     inc    temp            ; add 1 to the result
  415.     adc    word ptr temp+2,0    ;  ...
  416. dividel3:
  417.     shl    bx,1            ; shift all 64 bits
  418.     rcl    cx,1            ;  ...
  419.     rcl    ax,1            ;  ...
  420.     rcl    dx,1            ;  ...
  421.     dec    byte ptr temp+4     ; time to quit?
  422.     jnz    dividel1        ;  nope.  try again.
  423.  
  424.     mov    ax,temp         ; copy the result to DX:AX
  425.     mov    dx,word ptr temp+2    ;  ...
  426.     cmp    sign,0            ; should we negate the result?
  427.     je    divides6        ;  nope.
  428.     not    ax            ;  yup.  flip signs.
  429.     not    dx            ;   ...
  430.     mov    bx,0            ;   ...
  431.     stc                ;   ...
  432.     adc    ax,0            ;   ...
  433.     adc    dx,0            ;   ...
  434. divides6:
  435.     jmp    short dividereturn
  436.  
  437. overd1:
  438.     mov    ax,0ffffh        ; overflow value
  439.     mov    dx,07fffh        ; overflow value
  440.     mov    overflow,1        ; flag overflow
  441.  
  442. dividereturn:                ; that's all, folks!
  443.     pop    si
  444.     pop    di
  445.     ret
  446. divide        endp
  447.  
  448. .MODEL    medium,c
  449.  
  450. .8086
  451.  
  452. .DATA
  453.  
  454. extrn temp_array:DWORD
  455.  
  456. .CODE
  457.  
  458. ; *************** Function toextra(tooffset,fromaddr, fromcount) *********
  459.  
  460. toextra proc    uses es di si, tooffset:word, fromaddr:word, fromcount:word
  461.         cld                             ; move forward
  462.         les     di, temp_array
  463.         add     di,tooffset             ; load to here
  464.     mov    si,fromaddr        ; load from here
  465.     mov    cx,fromcount        ; this many bytes
  466.     rep    movsb            ; do it.
  467. tobad:
  468.     ret                ; we done.
  469. toextra endp
  470.  
  471.  
  472. ; *************** Function fromextra(fromoffset, toaddr, tocount) *********
  473.  
  474. fromextra proc    uses es di si, fromoffset:word, toaddr:word, tocount:word
  475.     push    ds            ; save DS for a tad
  476.     pop    es            ; restore it to ES
  477.     cld                ; move forward
  478.     mov    di,toaddr        ; load to here
  479.         mov     cx,tocount              ; this many bytes
  480.         lds     si, temp_array
  481.         add     si,fromoffset           ;  ..
  482.     rep    movsb            ; do it.
  483. frombad:
  484.     push    es            ; save ES again.
  485.     pop    ds            ; restore DS
  486.     ret                ; we done.
  487. fromextra endp
  488.  
  489.  
  490. ; *************** Function cmpextra(cmpoffset,cmpaddr, cmpcount) *********
  491.  
  492. cmpextra proc    uses es di si, cmpoffset:word, cmpaddr:word, cmpcount:word
  493.         cld                             ; move forward
  494.         les     di, temp_array
  495.         add     di,cmpoffset            ; load to here
  496.     mov    si,cmpaddr        ; load from here
  497.     mov    cx,cmpcount        ; this many bytes
  498.     rep    cmpsb            ; do it.
  499.     jnz    cmpbad            ; failed.
  500.     mov    ax,0            ; 0 == true
  501.     jmp    cmpend
  502. cmpbad:
  503.     mov    ax,1            ; 1 == false
  504. cmpend:
  505.     ret                ; we done.
  506. cmpextra    endp
  507.  
  508.     end
  509.